﻿#include "pch.h"
#include "qgp/qgach.h"

namespace _qgp
{
	static qbPixelProp ImplPixelTable[] =
	{
		{QGCF_NONE, "NONE", 0, 0, 0, 0, 0, 0, 0, 0, 0, QGCFF_NONE, false},

		{QGCF8_L, "L8", 1, 0, 0, 0, 0, 0, 0, 0, 0, QGCFF_NONE, false},
		{QGCF16_L, "L16", 2, 0, 0, 0, 0, 0, 0, 0, 0, QGCFF_NONE, false},

		{QGCF16_RGB, "R5G6B5", 2, 3, 11, 2, 5, 3, 0, 8, 0, QGCFF_NONE, false},
		{QGCF16_RGBA, "A1R5B5G5", 2, 3, 10, 3, 5, 3, 0, 7, 15, QGCFF_ALPHA, true},

		{QGCF32_RGB, "X8R8G8B8", 4, 0, 16, 0, 8, 0, 0, 8, 24, QGCFF_NONE, false},
		{QGCF32_RGBA, "A8R8G8B8", 4, 0, 16, 0, 8, 0, 0, 0, 24, QGCFF_ALPHA, true},
		{QGCF32_BGR, "X8B8G8R8", 4, 0, 0, 0, 8, 0, 16, 8, 24, QGCFF_BGR, false},
		{QGCF32_BGRA, "A8B8G8R8", 4, 0, 0, 0, 8, 0, 16, 0, 24, QGCFF_ALPHA | QGCFF_BGR, true},

		{QGCF16F_R, "R16", 2, 0, 0, 0, 0, 0, 0, 0, 0, QGCFF_FLOAT, false},
		{QGCF64F_BGRA, "B16G16R16A16", 8, 0, 0, 0, 0, 0, 0, 0, 0, QGCFF_ALPHA | QGCFF_FLOAT | QGCFF_BGR, true},

		{QGCF32F_R, "R32", 4, 0, 0, 0, 0, 0, 0, 0, 0, QGCFF_FLOAT, false},
		{QGCF128F_BGRA, "B32G32R32A32", 16, 0, 0, 0, 0, 0, 0, 0, 0, QGCFF_ALPHA | QGCFF_FLOAT | QGCFF_BGR, true},

		{QGCF_DXT1, "DXT1", 0, 0, 0, 0, 0, 0, 0, 0, 0, QGCFF_ALPHA | QGCFF_COMPRESS, true},
		{QGCF_DXT2, "DXT2", 0, 0, 0, 0, 0, 0, 0, 0, 0, QGCFF_ALPHA | QGCFF_COMPRESS, true},
		{QGCF_DXT3, "DXT3", 0, 0, 0, 0, 0, 0, 0, 0, 0, QGCFF_ALPHA | QGCFF_COMPRESS, true},
		{QGCF_DXT4, "DXT4", 0, 0, 0, 0, 0, 0, 0, 0, 0, QGCFF_ALPHA | QGCFF_COMPRESS, true},
		{QGCF_DXT5, "DXT5", 0, 0, 0, 0, 0, 0, 0, 0, 0, QGCFF_ALPHA | QGCFF_COMPRESS, true},
	};
}

//
kbool qgAchSupp::TestAlpha(qgColorFormat fmt)
{
	k_assert_0((ksize_t)fmt < K_COUNTOF(_qgp::ImplPixelTable));
	return _qgp::ImplPixelTable[fmt].alpha;
}

//
const qbPixelProp& qgAchSupp::ToPixelProp(qgColorFormat fmt)
{
	// bpp가 0이면 현재 사용할 수 없음
	k_assert_0((ksize_t)fmt < K_COUNTOF(_qgp::ImplPixelTable));
	return _qgp::ImplPixelTable[fmt];
}

//
kuint qgAchSupp::UnsafePackPixel(qgColorFormat fmt, kbyte r, kbyte g, kbyte b, kbyte a)
{
	return PackPixel(_qgp::ImplPixelTable[fmt], r, g, b, a);
}

//
kint qgAchSupp::LayoutTypeToSize(qgLoType type)
{
	static kint sSize[QGLOT_MAX_VALUE] =
	{
		1 * sizeof(float),
		2 * sizeof(float),
		3 * sizeof(float),
		4 * sizeof(float),
		2 * sizeof(khalf),
		4 * sizeof(khalf),
		2 * sizeof(kbyte),
		4 * sizeof(kbyte),
		4 * sizeof(kbyte),
		2 * sizeof(kushort),
		4 * sizeof(kushort),
		2 * sizeof(kushort),
		4 * sizeof(kbyte),
	};

	static_assert(QGLOT_MAX_VALUE == K_COUNTOF(sSize), "VertexLayoutType count mismatch.");

	k_assert(type >= 0 && type < K_COUNTOF(sSize), "range error");

	return sSize[type];
}

//
const char* qgAchSupp::ShaderTypeToString(qgShaderType type)
{
	static const char* sNames[] =
	{
		"VertexShader",
		"PixelShader",
		"GeometryShader",
		"ShaderEffect",
	};

	k_assert(type >= 0 && type < K_COUNTOF(sNames), "range error");

	return sNames[type];
}

//
const char* qgAchSupp::ShaderDataToString(qgShaderData type)
{
	static const char* sNames[] =
	{
		"UNKNOWN",
		"FLOAT1",
		"FLOAT2",
		"FLOAT3",
		"FLOAT4",
		"FLOAT16",
		"INT1",
		"INT2",
		"INT3",
		"INT4",
		"BYTE1",
		"BYTE2",
		"BYTE3",
		"BYTE4",
		"SAMPLER1D",
		"SAMPLER2D",
		"SAMPLER3D",
		"SAMPLERCUBE",
	};

	//static_assert(K_COUNTOF(sNames) == QGSHDD_MAX_VALUE, "invalid shader data count");

	k_assert(type >= 0 && type < K_COUNTOF(sNames), "range error");

	return sNames[type];
}

//
bool qgFwSupp::CheckHeadAndTail(kStream* stm)
{
	qbFwHsHead hsh;
	if (stm->Read(&hsh, 0, sizeof(qbFwHsHead)) != sizeof(qbFwHsHead) ||
		hsh.hdr != K_MAKEFOURCC('S', 'B', 'Q', 'G') ||
		hsh.version != 10)
		return false;

#if 0
	qbFwHsTail hst;
	if (!stm->Seek(sizeof(qbFwHsTail), KSEEK_END) ||
		stm->Read(&hst, 0, sizeof(qbFwHsTail)) != sizeof(qbFwHsTail) ||
		hst.hdr != K_MAKEFOURCC('E', 'N', 'D', 'Q') ||
		hst.version != hsh.version ||
		hst.revision != hsh.revision)
		return false;
#endif

	stm->Seek(sizeof(qbFwHsHead), KSEEK_BEGIN);

	return true;
}

//
bool qgFwSupp::CheckHeadAndTail(kconstpointer data, kint size)
{
	if ((ksize_t)size < (sizeof(qbFwHsHead)+sizeof(qbFwHsTail)+sizeof(qbFwHsItem)))
		return false;

	const qbFwHsHead* phh = (const qbFwHsHead*)data;
	if (phh->hdr != K_MAKEFOURCC('S', 'B', 'Q', 'G') ||
		phh->version != 10)
		return false;

	const qbFwHsTail* pht = (const qbFwHsTail*)((const kbyte*)data + size - sizeof(qbFwHsTail));
	if (pht->version != phh->version ||
		pht->revision != phh->revision)
		return false;

	return true;
}
